package edu.unc.comp410.colemangeer.model;

import java.util.Set;

import org.apache.log4j.Logger;

import edu.unc.comp410.colemangeer.demos.ShoppingCartDemo;



// Tax rule implementations must inherit from this class
// Also, static methods here encode the tax rules

public abstract class TaxRule implements ITaxComputer {

	/*	Tax will be computed for each state/province and each country.

	USA - Add 10% to the total including any state taxes.
	Canada - Add 3% to the total before provincial taxes.

	California - 4.5% tax on all items except
		Magical - exempt from tax
		Weapon - 21%

	Texas - 3% tax on all items except
		Magical - 11% 
		Weapon - exempt from tax
		Magical + Weapon = 31%

	North Carolina - 4% tax on all items except
		Book - 9% tax

	In lieu of specifying the tax rules for each state,
		Use California tax rates for all states/provinces that begin with
			the letters A-G
		Use North Carolina tax rates for all states/provinces that begin with
			the letters H-S
		Use Texax tax rates for all states/provinces that begin with
			the letter T.
		No tax for all states/provinces that begin with the letters U-Z*/

	private static Logger log = Logger.getLogger(TaxRule.class);
	
	private static final double US_TAX_RATE = 10.0;
	private static final double CANADA_TAX_RATE = 3.0;

	private static final double CA_TAX_RATE = 4.5;
	private static final double CA_MAGIC_TAX_RATE = 0;
	private static final double CA_WEAPON_TAX_RATE = 21.0;

	private static final double TX_TAX_RATE = 3.0;
	private static final double TX_MAGIC_TAX_RATE = 11.0;
	private static final double TX_WEAPON_TAX_RATE = 0;
	private static final double TX_MAGIC_AND_WEAPON_TAX_RATE = 31.0;

	private static final double NC_TAX_RATE = 4.0;
	private static final double NC_BOOK_TAX_RATE = 9.0;

	private static final double NO_TAX_TAX_RATE = 0.0;

	public static TaxRule getTaxRuleForCountry(TaxCountry country){
		if( country.equals(TaxCountry.CANADA)){
			return new CanadianTaxRule();
		}
		else{
			return new AmericanTaxRule();
		}
	}

	public static double getStateTaxRate(TaxRegion taxRegion, Set<ProductCategory> categories){
		
		switch (taxRegion){
		case NC:
			if (categories.contains(ProductCategory.BOOK)){
				log.warn("NC book rate");
				return NC_BOOK_TAX_RATE;
			}
			else{
				log.warn("NC state rate");
				return NC_TAX_RATE;
			}
		case CA:
			if(categories.contains(ProductCategory.WEAPON)){
				log.warn("CA weapon rate");
				return CA_WEAPON_TAX_RATE;
			}
			else if(categories.contains(ProductCategory.MAGICAL)){
				log.warn("CA magical rate");
				return CA_MAGIC_TAX_RATE;
			}
			else{
				log.warn("CA rate");
				return CA_TAX_RATE;
			}
		case TX:
			//log.info("Texas tax rules!");
			if(categories.contains(ProductCategory.MAGICAL)){
				if(categories.contains(ProductCategory.WEAPON)){
					//MAGICAL WEAPON
					log.warn("TX magical weapon rate");
					return TX_MAGIC_AND_WEAPON_TAX_RATE;
				}
				else{
					//MAGICAL
					log.warn("TX magical rate");
					return TX_MAGIC_TAX_RATE;
				}
			}
			else if(categories.contains(ProductCategory.WEAPON)){
				//WEAPON
				log.warn("TX weapon rate");
				return TX_WEAPON_TAX_RATE;

			}

			else{
				//TX DEFAULT
				log.warn("TX rate");
				return TX_TAX_RATE;

			}
		case NO_TAX:
			log.warn("No tax rate");
			return NO_TAX_TAX_RATE;
		default:
			log.warn("No tax rate");
			return NO_TAX_TAX_RATE;
		}
	}

	public static double getCountryTaxRate(TaxCountry taxCountry){
		switch(taxCountry){
		case USA:
			return  US_TAX_RATE;
		case CANADA:
			return CANADA_TAX_RATE;
		default:
			return US_TAX_RATE;
		}
	}
	
	private TaxCountry taxCountry;
	private TaxRegion taxRegion;

	public abstract double computeTaxPrice(double basePrice, Set<ProductCategory> categories);

	public  double applyRegionTax(double price,Set<ProductCategory> categories){
		if (taxCountry == null || taxRegion == null){
			throw new IllegalStateException();
		}
		double regionRate = TaxRule.getStateTaxRate(taxRegion, categories);
		log.warn("Applying region tax rate of " + regionRate + " percent");
		return (1 + (TaxRule.getStateTaxRate(taxRegion, categories)/100)) * price;
	}
	public  double applyCountryTax(double price){
		double countryRate = TaxRule.getCountryTaxRate(taxCountry);
		log.warn("Applying country tax rate of " + countryRate + " percent");
		return (1 + (countryRate/100 ))* price;
	}
	
	public TaxCountry getTaxCountry() {
		return taxCountry;
	}

	public void setTaxCountry(TaxCountry taxCountry) {
		this.taxCountry = taxCountry;
	}

	public TaxRegion getTaxRegion() {
		return taxRegion;
	}

	public void setTaxRegion(TaxRegion taxRegion) {
		this.taxRegion = taxRegion;
	}
}
